/*
 * Copyright (c) 2014.
 * Jackrex
 */

package com.cjjd.c.utils;

import android.text.InputFilter;
import android.text.Spanned;
import android.text.TextUtils;
import android.util.Base64;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串操作工具包
 */
public class StringUtil {

    private final static Pattern emailer = Pattern.compile("\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*");

    /**
     * 判断给定字符串是否空白串。 空白串是指由空格、制表符、回车符、换行符组成的字符串
     * 若输入字符串为null或空字符串，返回true
     *
     * @param input
     * @return boolean
     */
    public static boolean isEmpty(String input) {
        if (input == null || "".equals(input))
            return true;

        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断是不是一个合法的电子邮件地址
     *
     * @param email
     * @return
     */
    public static boolean isEmail(String email) {
        if (email == null || email.trim().length() == 0)
            return false;
        return emailer.matcher(email).matches();
    }


    private static final double EARTH_RADIUS = 6378137;

    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }


    public static boolean isChinese(char a) {
        int v = (int) a;
        return ((v >= 19968 && v <= 171941));
    }

    public static boolean isChinese(String s) {
        if (null == s || "".equals(s.trim()))
            return false;
        for (int i = 0; i < s.length(); i++) {
            if (!isChinese(s.charAt(i)))
                return false;
        }
        return true;
    }

    public static boolean containsChinese(String s) {
        if (null == s || "".equals(s.trim()))
            return false;
        for (int i = 0; i < s.length(); i++) {
            if (isChinese(s.charAt(i)))
                return true;
        }
        return false;
    }

    public static String encodeHexString(byte[] bytes) {
        StringBuilder buffer = new StringBuilder();
        StringUtil.encodeHexString(bytes, buffer);
        return buffer.toString();
    }

    public static void encodeHexString(byte[] bytes, StringBuilder buffer) {
        for (byte b : bytes) {
            int hi = (b >>> 4) & 0x0f;
            int lo = (b >>> 0) & 0x0f;
            buffer.append(Character.forDigit(hi, 16));
            buffer.append(Character.forDigit(lo, 16));
        }
    }

    /**
     * base64 加密
     *
     * @param str
     * @return
     */
    public static String base64encode(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }
        try {
            return new String(Base64.encode(str.getBytes("UTF-8"), Base64.DEFAULT), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String base64decode(String str) {
        if (TextUtils.isEmpty(str)) {
            return null;
        }
        try {
            return new String(Base64.decode(str.getBytes(), Base64.DEFAULT), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getMD5(String str) {

        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.reset();
            messageDigest.update(str.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
        } catch (UnsupportedEncodingException e) {
        }
        byte[] byteArray = messageDigest.digest();
        StringBuffer md5StrBuff = new StringBuffer();
        for (int i = 0; i < byteArray.length; i++) {
            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1) {
                md5StrBuff.append("0").append(
                        Integer.toHexString(0xFF & byteArray[i]));
            } else {
                md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
            }
        }
//        return md5StrBuff.substring(8, 24).toString();
        return md5StrBuff.toString();
    }

    private static byte[] encode(String str) throws Exception {

        byte[] btInput = str.getBytes("UTF-8");
        MessageDigest mdInst = MessageDigest.getInstance("MD5");
        mdInst.update(btInput);
        byte[] md = mdInst.digest();
        return md;

    }

    public static String convertStreamToString(InputStream is)
            throws IOException {
        if (is != null) {

            StringBuilder sb = new StringBuilder();
            String line;

            try {
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(is, "UTF-8"));
                while ((line = reader.readLine()) != null) {
                    sb.append(line).append("\n");
                }
            } finally {
                is.close();
            }
            return sb.toString();
        } else {
            return "";
        }
    }

    public static boolean checkEmail(String email) {
        boolean flag = false;
        try {
            String check = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
            Pattern regex = Pattern.compile(check);
            Matcher matcher = regex.matcher(email);
            flag = matcher.matches();
        } catch (Exception e) {
            flag = false;
        }

        return flag;
    }

    /**
     * 判断是否是手机号
     *
     * @param mobiles
     * @return
     */
    public static boolean isMobile(String mobiles) {
        boolean flag = false;
        if (mobiles != null && mobiles.length() == 11 && mobiles.startsWith("1"))
            flag = true;
        return flag;
    }

    public static boolean isNum(String number) {
        boolean flag = false;
        try {
            Pattern p = Pattern.compile("^[0-9]{5}$");
            Matcher m = p.matcher(number);
            flag = m.matches();
        } catch (Exception e) {
            flag = false;
        }
        return flag;
    }

    /**
     * 身份证号码验证
     * 1、号码的结构 公民身份号码是特征组合码，由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为：六位数字地址码，
     * 八位数字出生日期码，三位数字顺序码和一位数字校验码。
     * 2、地址码(前六位数）
     * 表示编码对象常住户口所在县(市、旗、区)的行政区划代码，按GB/T2260的规定执行。
     * 3、出生日期码（第七位至十四位）
     * 表示编码对象出生的年、月、日，按GB/T7408的规定执行，年、月、日代码之间不用分隔符。
     * 4、顺序码（第十五位至十七位）
     * 表示在同一地址码所标识的区域范围内，对同年、同月、同日出生的人编定的顺序号， 顺序码的奇数分配给男性，偶数分配给女性。
     * 5、校验码（第十八位数）
     * （1）十七位数字本体码加权求和公式 S = Sum(Ai * Wi), i = 0, ... , 16 ，先对前17位数字的权求和
     * Ai:表示第i位置上的身份证号码数字值 Wi:表示第i位置上的加权因子 Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4
     * 2
     * （2）计算模 Y = mod(S, 11)
     * （3）通过模得到对应的校验码 Y: 0 1 2 3 4 5 6 7 8 9 10 校验码: 1 0
     * X 9 8 7 6 5 4 3 2
     */

    /**
     * 功能：身份证的有效验证
     *
     * @param IDStr 身份证号
     * @return 有效：返回"" 无效：返回String信息
     * @throws ParseException
     */
    @SuppressWarnings("unchecked")
    public static String IDCardValidate(String IDStr) throws ParseException {
        String errorInfo = "";// 记录错误信息
        String[] ValCodeArr = {"1", "0", "X", "9", "8", "7", "6", "5", "4",
                "3", "2"};
        String[] Wi = {"7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7",
                "9", "10", "5", "8", "4", "2"};
        String Ai = "";
        // ================ 号码的长度 15位或18位 ================
        if (IDStr.length() != 15 && IDStr.length() != 18) {
            errorInfo = "身份证号码长度应该为15位或18位";
            return errorInfo;
        }
        // =======================(end)========================

        // ================ 数字 除最后以为都为数字 ================
        if (IDStr.length() == 18) {
            Ai = IDStr.substring(0, 17);
        } else if (IDStr.length() == 15) {
            Ai = IDStr.substring(0, 6) + "19" + IDStr.substring(6, 15);
        }
        if (isNumeric(Ai) == false) {
            //errorInfo = "身份证15位号码都应为数字 ; 18位号码除最后一位外，都应为数字" + Ai;
            errorInfo = "身份证15位号码都应为数字 ; 18位号码除最后一位外，都应为数字";
            return errorInfo;
        }
        // =======================(end)========================

        // ================ 出生年月是否有效 ================
        String strYear = Ai.substring(6, 10);   // 年份
        String strMonth = Ai.substring(10, 12); // 月份
        String strDay = Ai.substring(12, 14);   // 月份
        if (isDate(strYear + "-" + strMonth + "-" + strDay) == false) {
            errorInfo = "身份证生日无效";
            return errorInfo;
        }
        GregorianCalendar gc = new GregorianCalendar();
        SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
        try {
            if ((gc.get(Calendar.YEAR) - Integer.parseInt(strYear)) > 150
                    || (gc.getTime().getTime() - s.parse(
                    strYear + "-" + strMonth + "-" + strDay).getTime()) < 0) {
                errorInfo = "身份证生日不在有效范围";
                return errorInfo;
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (Integer.parseInt(strMonth) > 12 || Integer.parseInt(strMonth) == 0) {
            errorInfo = "身份证月份无效";
            return errorInfo;
        }
        if (Integer.parseInt(strDay) > 31 || Integer.parseInt(strDay) == 0) {
            errorInfo = "身份证日期无效";
            return errorInfo;
        }
        // =====================(end)=====================

        // ================ 地区码时候有效 ================
        Hashtable h = GetAreaCode();
        if (h.get(Ai.substring(0, 2)) == null) {
            errorInfo = "身份证地区编码错误";
            return errorInfo;
        }
        // ==============================================

        // ================ 判断最后一位的值 ================
        int TotalmulAiWi = 0;
        for (int i = 0; i < 17; i++) {
            TotalmulAiWi = TotalmulAiWi
                    + Integer.parseInt(String.valueOf(Ai.charAt(i)))
                    * Integer.parseInt(Wi[i]);
        }
        int modValue = TotalmulAiWi % 11;
        String strVerifyCode = ValCodeArr[modValue];
        Ai = Ai + strVerifyCode;

        if (IDStr.length() == 18) {
            if (Ai.equals(IDStr) == false) {
                errorInfo = "身份证无效，不是合法的身份证号码";
                return errorInfo;
            }
        } else {
            return "";
        }
        // =====================(end)=====================
        return "";
    }

    /**
     * 功能：判断字符串是否为日期格式
     *
     * @param strDate
     * @return
     */
    public static boolean isDate(String strDate) {
        Pattern pattern = Pattern
                .compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$");
        Matcher m = pattern.matcher(strDate);
        return m.matches();
    }

    /**
     * 功能：设置地区编码
     *
     * @return Hashtable 对象
     */
    @SuppressWarnings("unchecked")
    private static Hashtable GetAreaCode() {
        Hashtable hashtable = new Hashtable();
        hashtable.put("11", "北京");
        hashtable.put("12", "天津");
        hashtable.put("13", "河北");
        hashtable.put("14", "山西");
        hashtable.put("15", "内蒙古");
        hashtable.put("21", "辽宁");
        hashtable.put("22", "吉林");
        hashtable.put("23", "黑龙江");
        hashtable.put("31", "上海");
        hashtable.put("32", "江苏");
        hashtable.put("33", "浙江");
        hashtable.put("34", "安徽");
        hashtable.put("35", "福建");
        hashtable.put("36", "江西");
        hashtable.put("37", "山东");
        hashtable.put("41", "河南");
        hashtable.put("42", "湖北");
        hashtable.put("43", "湖南");
        hashtable.put("44", "广东");
        hashtable.put("45", "广西");
        hashtable.put("46", "海南");
        hashtable.put("50", "重庆");
        hashtable.put("51", "四川");
        hashtable.put("52", "贵州");
        hashtable.put("53", "云南");
        hashtable.put("54", "西藏");
        hashtable.put("61", "陕西");
        hashtable.put("62", "甘肃");
        hashtable.put("63", "青海");
        hashtable.put("64", "宁夏");
        hashtable.put("65", "新疆");
        hashtable.put("71", "台湾");
        hashtable.put("81", "香港");
        hashtable.put("82", "澳门");
        hashtable.put("91", "国外");
        return hashtable;
    }

    /**
     * 功能：判断字符串是否为数字
     *
     * @param str
     * @return
     */
    private static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str);
        return isNum.matches();
    }


    /**
     * 计算double类型的value1和value2的差值，并以string返回
     * value1 - value2
     *
     * @param value1
     * @param value2
     * @return
     */
    public static String calculate(String value1, String value2) {
        //LogUtil.e("xyd","value1 :" + Double.parseDouble(value1));
        //LogUtil.e("xyd","value2 :" + Double.parseDouble(value2));
        //LogUtil.e("xyd","value1-2 :" + (Double.parseDouble(value1) - Double.parseDouble(value2)) + "");
        return Double.parseDouble(value1) - Double.parseDouble(value2) + "";
    }


    /**
     * 计算Double类型的两个利率值，除以100，之后得到百分值，以string返回
     *
     * @param value
     * @return
     */
    public static String calculateRate(String value) {
        return Double.parseDouble(value) / 100 + "";
    }

    /**
     * 计算Double类型的两个利率值，除以100，之后得到百分值，以string返回
     *
     * @param value1
     * @param value2
     * @return
     */
    public static String calculateRate(String value1, String value2) {
        return (Double.parseDouble(value1) - Double.parseDouble(value2)) / 100 + "";
    }

    /**
     * 四舍五入
     * 获取两位有效数字的double值
     *
     * @param doubleValue
     * @return
     */
    public static String getDecimalValue(String doubleValue) {
        double v = Double.parseDouble(doubleValue);
        DecimalFormat decimalFormat = new DecimalFormat("0.00");
        String format = decimalFormat.format(v);
        return format;
    }


    /**
     * 获取两个数字的差的double值
     *
     * @param doubleValue1
     * @param doubleValue2
     * @return
     */
    public static String getSubDecimalValue(String doubleValue1, String doubleValue2) {
        double v1 = Double.parseDouble(doubleValue1);
        double v2 = Double.parseDouble(doubleValue2);
        DecimalFormat decimalFormat = new DecimalFormat("0.00");
        String format = decimalFormat.format(v1 - v2);
        return format;
    }

    /**
     * 获取两个数字的和的double值
     *
     * @param doubleValue1
     * @param doubleValue2
     * @return
     */
    public static String getAddDecimalValue(String doubleValue1, String doubleValue2) {
        double v1 = Double.parseDouble(doubleValue1);
        double v2 = Double.parseDouble(doubleValue2);
        DecimalFormat decimalFormat = new DecimalFormat("0.00");
        String format = decimalFormat.format(v1 + v2);
        return format;
    }

    /**
     * 把毫秒转化成日期
     *
     * @param dateFormat(日期格式，例如：MM/ dd/yyyy HH:mm:ss)
     * @param millSec(毫秒数)
     * @return
     */
    public static String longToDate(String dateFormat, Long millSec) {
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        Date date = new Date(millSec);
        return sdf.format(date);
    }

    /**
     * 对日期时间进行格式化
     *
     * @param time
     * @return
     */
    public static String stringToFormat(String time) {
        long longtime = Long.valueOf(time);
        Date date = new Date(longtime);
        return String.format("%tF", date);
    }


    /**
     * 长度的过滤器
     */
    public static InputFilter lengthfilter = new InputFilter() {
        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            String so = source.toString();      // 输入的字符串，如果输入的是单个字符，就是单个，如果是粘贴的，则是粘贴的字符串
            String de = dest.toString();        // 输入的总字符串，但不包括so

            if ("".equals(so) || end == 0) {
                de = de.substring(0, dstart) + de.substring(dend, de.length());
            } else {
                de = de.substring(0, dstart) + so + de.substring(dend, de.length());
            }

            System.out.println(de);


            //Pattern pattern = Pattern.compile("^\\d{0,9}\\.?(?:\\.\\d{0,2})?$");
            Pattern pattern = Pattern.compile("^\\d{0,9}\\.?(\\.\\d{1,2})?$");
            //Pattern pattern = Pattern.compile("^\\d{0,9}\\.?$");
            Matcher matcher = pattern.matcher(de);


            if (matcher.find()) {
                System.out.println("匹配到：" + de);
                System.out.println("--------------");
                return null;
            } else {
                System.out.println("没匹配到：" + dest.toString());
                System.out.println("--------------");
                return "";
            }
        }
    };


    /**
     * 获取带星号的名字
     *
     * @param name
     * @return
     */
    public static String getSignName(String name) {

        if (TextUtils.isEmpty(name)) {
            return "";
        }
        return name.substring(0, 1) + "**";
    }


    /**
     * 获取带星号的身份证号码
     *
     * @param idNumber
     * @return
     */
    public static String getSignIdNum(String idNumber) {

        if (TextUtils.isEmpty(idNumber)) {
            return "";
        }
        try {
            return idNumber.substring(0, 4) + "*********" + idNumber.substring(idNumber.length() - 4, idNumber.length());
        } catch (Exception e) {
            return "******";
        }
    }

    /**
     * 获取带星号的手机号码
     *
     * @param phone
     * @turn
     */
    public static String getSignPhone(String phone) {

        if (TextUtils.isEmpty(phone)) {
            return "";
        }
        if (phone.length() != 11) {
            return phone;
        }
        return phone.substring(0, 3) + "***" + phone.substring(phone.length() - 4, phone.length());
    }

    /**
     * 获取带星号的银行卡号码
     *
     * @param bankNum
     * @turn
     */
    public static String getSignBankNum(String bankNum) {

        if (TextUtils.isEmpty(bankNum)) {
            return "";
        }
        return bankNum.substring(0, 4) + "*********" + bankNum.substring(bankNum.length() - 4, bankNum.length());
    }


    public static String getDistanceShow(String distance) {
        String distanceShow = "";
        double dis = 0;
        try {
            dis = Double.parseDouble(distance);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }

        if (dis < 500) {
            distanceShow = "据您 < 500 米";
        } else if (dis < 1000) {
            distanceShow = "据您 < 1 km";
        }else if (dis < 2000) {
            distanceShow = "据您 < 2 km";
        }else if (dis < 3000) {
            distanceShow = "据您 < 3 km";
        }else if (dis < 4000) {
            distanceShow = "据您 < 4 km";
        }else if (dis < 5000) {
            distanceShow = "据您 < 5 km";
        }else if (dis < 6000) {
            distanceShow = "据您 < 6 km";
        }else if (dis < 7000) {
            distanceShow = "据您 < 7 km";
        }else if (dis < 8000) {
            distanceShow = "据您 < 8 km";
        }else if (dis < 9000) {
            distanceShow = "据您 < 9 km";
        }else if (dis < 10000) {
            distanceShow = "据您 < 10 km";
        }else {
            distanceShow = "据您 " + (int)dis + "米";
        }

        return distanceShow;
    }

}
